


#ifndef __QE_STRING_H__
#define __QE_STRING_H__



#include "autocheck.h"
#include "autoconfig.h"
#include "qe_def.h"


#if defined(HAVE_STDARG_H)
#include <stdarg.h>
#else
#error "System don't have stdarg.h"
#endif



/**
 * String Builder
 */
typedef struct {
	char *p;
	char *head;
	int   max;
	int   len;
} qe_strb;

int qe_strb_args(qe_strb *strb, const char *fmt, ...);
qe_strb qe_strb_frombuf(char *buf, int size);

#define qe_strb_none()			    {QE_NULL, QE_NULL, 0, 0}
#define qe_strb_init(s, max)	    {(s), (s), max, qe_strlen(s)}

#define qe_strb_string(p, s)		(qe_strb_args(&p, "%s", s))
#define qe_strb_int(p, n)		    (qe_strb_args(&p, "%d", n))
#define qe_strb_uint(p, n)		    (qe_strb_args(&p, "%u", n))
#define qe_strb_hex(p, h)		    (qe_strb_args(&p, "%x", h))
#define qe_strb_format(p, fmt, ...)	(qe_strb_args(&p, fmt, ##__VA_ARGS__))



#if defined(CONFIG_NANO)

static inline qe_bool qe_isspace(char c)
{
    unsigned char uc = (unsigned char)c;
    return (uc == ' '  ||
            uc == '\f' ||
            uc == '\n' ||
            uc == '\r' ||
            uc == '\t' ||
            uc == '\v');
}

static inline char qe_tolower(char c)
{
    if (c >= 'A' && c <= 'Z') {
        return c + 32;
    }
    return c;
}

static inline char qe_toupper(char c)
{
    if (c >= 'a' && c <= 'z') {
        return c - 32;
    }
    return c;
}

static inline qe_bool qe_isalpha(char c)
{
    if (((c >= 'A') && (c <= 'Z')) ||
        ((c >= 'a') && (c <= 'z'))) {
        return qe_true;
    }
    return qe_false;
}

static inline qe_bool qe_isdigit(char c)
{
    if (c < '0' || c > '9')
        return qe_false;
    return qe_true;
}

int qe_strcmp(const char *cs, const char *ct);
int qe_strncmp(const char *cs, const char *ct, qe_size count);
char *qe_strcat(char *dest, const char *src);
char *qe_strncat(char *dest, const char *src, qe_size count);
char *qe_strchr(const char *s, int c);
char *qe_strstr(const char *s1, const char *s2);
char *qe_strcpy(char *dest, const char *src);
char *qe_strncpy(char *dest, const char *src, qe_size count);
char *qe_strdup(const char *s);
char *qe_strndup(const char *s, qe_size n);
char *qe_strpbrk(const char *cs, const char *ct);
char *qe_strtok(char *s, const char *ct);
char *qe_strsep(char **s, const char *ct);
char *qe_strswab(const char *s);
void *qe_memchr(const void *s, int c, qe_size n);
const char *qe_strchrnul(const char *s, int c);
qe_size qe_strlen(const char *s);
qe_size qe_strnlen(const char *s, qe_size count);
qe_size qe_strlcpy(char *dest, const char *src, qe_size size);
qe_size qe_strcspn(const char *s, const char *reject);
qe_size qe_strspn(const char *s, const char *accept);
void qe_putc(char c);
int qe_printf(const char *fmt, ...);
int qe_sprintf(char *buffer, const char *format, ...);
int qe_snprintf(char *buf, qe_size size, const char *fmt, ...);
int qe_vsprintf(char *buf, const char *format, va_list arg_ptr);
int qe_vsnprintf(char *buf, qe_size size, const char *fmt, va_list args);
int qe_vasprintf(char **strp, const char *fmt, va_list ap);

qe_double qe_strtof(const char *s, char **endptr);
qe_s64 qe_strtol(const char *str, char **endptr, int base);
#else

#if defined(HAVE_STDARG_H)
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define qe_isspace      isspace
#define qe_isdigit      isdigit
#define qe_isalpha      isalpha
#define qe_tolower      tolower
#define qe_toupper      toupper
#define qe_strlen       strlen
#define qe_strcpy       strcpy
#define qe_strncpy      strncpy
#define qe_strcmp       strcmp
#define qe_strncmp      strncmp
#define qe_strstr       strstr
#define qe_strchr       strchr
#define qe_strcat       strcat
#define qe_strdup       strdup
#define qe_strtok       strtok
#define qe_printf       printf
#define qe_sprintf      sprintf
#define qe_snprintf     snprintf
#define qe_vprintf      vprintf
#define qe_vsprintf     vsprintf
#define qe_vsnprintf    vsnprintf
#define qe_strtol       strtol
#define qe_strtof       strtof
#endif

#if defined(HAVE_VASPRINTF)
#deifne qe_vasprintf    vasprintf
#else
#if defined(HAVE_STDARG_H)
int qe_vasprintf(char **strp, const char *fmt, va_list ap);
#endif

#endif

#endif /* CONFIG_NANO */

qe_int qe_strtoi(qe_const_str s);
qe_ubase qe_hexstr_to_u32(qe_const_str str);

typedef struct {
    char *str;
    qe_size len;
    qe_size allocated_len;
} qe_string;

char *qe_strdup_format_args(const char *format, va_list args);
char *qe_strdup_format(const char *format, ...);

qe_string *qe_string_new(const char *init);
qe_string *qe_string_new_len(const char *init, qe_size len);
qe_string *qe_string_truncate(qe_string *string, qe_size len);
qe_string *qe_string_insert_len(qe_string *string, qe_base pos, 
    const char *val, qe_base len);
qe_string *qe_string_insert(qe_string *string, qe_offs pos,
    const char *val);
void qe_string_format(qe_string *string, const char *format, ...);
void qe_string_append_vprintf(qe_string *string, const char *format, va_list args);
void qe_string_append_format(qe_string *string, const char *format, ...);
qe_string *qe_string_prepend(qe_string *string, const char *val);
qe_string *qe_string_prepend_char(qe_string *string, char c);
qe_string *qe_string_prepend_len(qe_string *string, const char *val,
    qe_offs len);
qe_string *qe_string_append(qe_string *string, const char *val);
qe_string *qe_string_append_char(qe_string *string, char c);
qe_bool qe_string_equal(const qe_string *s1, const qe_string *s2);
qe_u32 qe_string_hash(const qe_string *str);
qe_string *qe_string_erase(qe_string *string, qe_offs pos, int len);
char *qe_string_free(qe_string *string, qe_bool free_segment);
char *qe_string_free_and_steal(qe_string *string);
qe_uint qe_string_replace(qe_string *string, const char *find, const char *replace, 
    qe_uint limit);

qe_const_str qe_byte_to_str(qe_uint bytes);
void qe_hexdump(qe_const_ptr buf, qe_uint len);


#endif /* __QE_STRING_H__ */
